home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / palette.c < prev    next >
C/C++ Source or Header  |  1996-05-17  |  11KB  |  534 lines

  1. #include "palette.hpp"
  2. #include "image.hpp"
  3. #include "macs.hpp"
  4. #include "dos.h"
  5. #include "video.hpp"
  6. #include "filter.hpp"
  7. #include "jmalloc.hpp"
  8. #include <math.h>
  9.  
  10. palette *lastl=NULL;
  11.  
  12. palette::palette(bFILE *fp)
  13. {
  14.   ncolors=fp->read_short();
  15.   pal=(color *)jmalloc(sizeof(color)*ncolors,"palette");
  16.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  17.   set_all_unused();
  18.   fp->read(pal,sizeof(color)*ncolors);
  19.   bg=0;
  20. }
  21.  
  22. palette::palette(spec_entry *e, bFILE *fp)
  23. {
  24.   fp->seek(e->offset,0);
  25.   ncolors=fp->read_short();
  26.   pal=(color *)jmalloc(sizeof(color)*ncolors,"palette");
  27.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  28.   set_all_unused();
  29.   fp->read(pal,sizeof(color)*ncolors);
  30.   bg=0;
  31. }
  32.  
  33. int palette::size()
  34. {
  35.   return ncolors*sizeof(color)+2;
  36. }
  37.  
  38. int palette::write(bFILE *fp)
  39. {
  40.   fp->write_short(ncolors);
  41.   return fp->write(pal,sizeof(color)*ncolors)==ncolors;
  42. }
  43.  
  44. int palette::find_closest(unsigned char r, unsigned char g, unsigned char b)
  45. {
  46.    unsigned char *cl=(unsigned char *)addr();
  47.    int c=0,d=0x100000,i,nd;
  48.    for (i=0;i<256;i++)
  49.    {
  50.      nd=((int)r-(int)(*cl))*((int)r-(int)(*cl)); cl++;
  51.      nd+=((int)g-(int)(*cl))*((int)g-(int)(*cl)); cl++;
  52.      nd+=((int)b-(int)(*cl))*((int)b-(int)(*cl)); cl++;
  53.      if (nd<d)
  54.      { c=i; d=nd; }
  55.    }
  56.    return c;
  57. }
  58.  
  59.  
  60. int palette::find_closest_non0(unsigned char r, unsigned char g, unsigned char b)
  61. {
  62.    unsigned char *cl=(unsigned char *)addr()+3;
  63.    int c=1,d=0x7fffffff,i,nd;
  64.    for (i=1;i<256;i++)
  65.    {
  66.      nd=((int)r-(int)(*cl))*((int)r-(int)(*cl)); cl++;
  67.      nd+=((int)g-(int)(*cl))*((int)g-(int)(*cl)); cl++;
  68.      nd+=((int)b-(int)(*cl))*((int)b-(int)(*cl)); cl++;
  69.      if (nd<d)
  70.      { c=i; d=nd; }
  71.    }
  72.    return c;
  73. }
  74.  
  75.  
  76. int palette::find_color(unsigned char r, unsigned char g, unsigned char b)
  77. {
  78.   int i,ub,mask,find;
  79.   for (i=0,ub=0,mask=128,find=-1;i<ncolors && find<0;i++)
  80.   {
  81.     if (usd[ub]&mask)
  82.       if (r==pal[i].red && b==pal[i].blue && g==pal[i].green)
  83.     find=i;
  84.     mask>>=1;
  85.     if (mask==0)
  86.     { mask=128; ub++; }
  87.   }
  88.   return find;
  89. }
  90.  
  91. long palette::getquad(int x)
  92. { char entry[4];
  93.   entry[3]=0;
  94.   entry[2]=pal[x].red;
  95.   entry[1]=pal[x].green;
  96.   entry[0]=pal[x].blue;
  97.   return *((long *)entry);
  98. }
  99.  
  100.  
  101. void palette::black_white()
  102. {
  103.   int i;
  104.   unsigned char r,g,b,gr;
  105.  
  106.   for (i=0;i<256;i++)
  107.   {
  108.     get(i,r,g,b);
  109.     gr=(unsigned char)((double) r*0.30+(double) g*0.59+(double)b*0.11);
  110.     set(i,gr,gr,gr);
  111.   }
  112. }
  113.  
  114. void palette::make_black_white()
  115. {
  116.   int i,c;
  117.   set(0,0,0,0);
  118.   for (i=1;i<ncolors;i++)
  119.   { c=(int)((double)i/(double)ncolors*(double)255);
  120.     set(i,c,c,c);
  121.   }
  122. }
  123.  
  124. void palette::set_rgbs()
  125. {
  126.   int i,v;
  127.   CHECK(ncolors==256);
  128.   for (i=0;i<64;i++)
  129.   {
  130.     if (i==0) v=0;
  131.     else
  132.     {
  133.       v=(int) ((double)i+(double)(sqrt(63-i)));
  134.       v<<=2;
  135.     }
  136.  
  137.     set(i,         i,     0,     0);            // reds 0-63
  138.     set(i+64,      0,     i,     0);
  139.     set(i+128,     0,     0,     i);       // blues 128-191
  140.     set(i+128+64,  v,     v,     v);        // whites .. rest
  141.   }
  142.   set_all_used();
  143. }
  144.  
  145. void palette::set_all_used()
  146. {
  147.   int i;
  148.   for (i=0;i<ncolors;i++) set_used(i);
  149. }
  150.  
  151. void palette::set_all_unused()
  152. {
  153.   int i;
  154.   for (i=0;i<ncolors;i++) set_unused(i);
  155. }
  156.  
  157.  
  158. palette *palette::copy()
  159. {
  160.   palette *p;
  161.   int i;
  162.   p=new palette(ncolors);
  163.   for (i=0;i<ncolors;i++)
  164.   {
  165.     if (used(i))
  166.       p->set_used(i);
  167.     else p->set_unused(i);
  168.     p->set(i,red(i),green(i),blue(i));
  169.   }
  170.   return p;
  171. }
  172.  
  173. void palette::set_used(int color_num)
  174. {
  175.   int x,b;
  176.   CHECK(color_num>=0 && color_num<ncolors);
  177.   x=color_num/8;
  178.   b=color_num%8;
  179.   usd[x]|=(128>>b);
  180. }
  181.  
  182. void palette::set_unused(int color_num)
  183. {
  184.   int x,b;
  185.   CHECK(color_num>=0 && color_num<ncolors);
  186.   x=color_num/8;
  187.   b=color_num%8;
  188.   usd[x]&=(0xff^(128>>b));
  189. }
  190.  
  191. int palette::used(int color_num)
  192. {
  193.   int x,b;
  194.   CHECK(color_num>=0 && color_num<ncolors);
  195.   x=color_num/8;
  196.   b=color_num%8;
  197.   return (usd[x]&(128>>b));
  198. }
  199.  
  200. int palette::add_color(unsigned int r, int unsigned g, int unsigned b, int closest_only)
  201. {
  202.   int i,f,u,c;
  203.   if (!closest_only)
  204.   {
  205.     for (i=ncolors-1,f=-1,u=-1;i>=0 && f<0;i--)
  206.     {
  207.       if (used(i))
  208.       {
  209.         if (pal[i].red==r && pal[i].green==g && pal[i].blue==b)
  210.     f=i;
  211.       }
  212.       else
  213.         u=i;
  214.     }
  215.   } else { f=-1; u=-1; }
  216.   if (f<0)
  217.   {
  218.     if (u>=0)
  219.     { pal[u].red=r;
  220.       pal[u].green=g;
  221.       pal[u].blue=b;
  222.       set_used(u);
  223.       f=u;
  224.     }
  225.     else
  226.     {
  227.       for (i=0,f=0,u=10000;i<ncolors;i++)
  228.       { c=(pal[i].red-r)*(pal[i].red-r)+
  229.       (pal[i].green-g)*(pal[i].green-g)+
  230.       (pal[i].blue-b)*(pal[i].blue-b);
  231.     if (c<u)
  232.     { f=i;
  233.       u=c;
  234.     }
  235.       }
  236.     }
  237.   } 
  238.   return f;
  239. }
  240.  
  241. void palette::defaults()
  242. {
  243.   int i;
  244.   set(0,0,0,0);
  245.   set_used(0);
  246.   for (i=1;i<ncolors;i++)
  247.     set_unused(i);
  248.   if (ncolors==256)
  249.     for (i=0;i<ncolors;i++)
  250.       set(i,RED3(i),GREEN3(i),BLUE2(i));
  251.   else if (ncolors==16)
  252.     for (i=0;i<ncolors;i++)
  253.       set(i,255-i&3,255-(i&4)>>2,255-(i&8)>>3);
  254.   else
  255.     for (i=0;i<ncolors;i++)
  256.       set(i,255-i%3,255-(i+1)%3,255-(i+2)%3);
  257. }
  258.  
  259. void palette::shift(int amount)
  260. {
  261.   int i;
  262.   unsigned char m;
  263.   if (amount<0)
  264.   {
  265.  
  266.     m=-amount;
  267.     for (i=0;i<ncolors*3;i++)
  268.       ((unsigned char *) pal)[i]>>=m;
  269.   }
  270.   else if (amount>0)
  271.   {
  272.     m=amount;
  273.     for (i=0;i<ncolors*3;i++)
  274.       ((unsigned char *) pal)[i]<<=m;
  275.   }
  276. }
  277.  
  278.  
  279.  
  280. void palette::set(int x, unsigned char red, char unsigned green, char unsigned blue)
  281. { CONDITION(x>=0 && x<ncolors,"Pallete::set passed bad x");
  282.   CONDITION((int)red<=ncolors && (int)green<=ncolors && (int)blue<=ncolors,
  283.         "pallette::set color values bigger than palette");
  284.   pal[x].red=red; pal[x].green=green; pal[x].blue=blue;
  285. }
  286.  
  287. void palette::get(int x, unsigned char &red, unsigned char &green, unsigned char &blue)
  288. { CONDITION(x>=0 && x<ncolors,"Pallete::get passed bad x");
  289.   red=pal[x].red; green=pal[x].green; blue=pal[x].blue;
  290. }
  291. palette::~palette()
  292. { if (pal) jfree(pal);
  293.   if (usd) jfree(usd);
  294. }
  295.  
  296. palette::palette(int number_colors)
  297. {
  298.   CONDITION(number_colors>0,"palette::constructor - need at least one color!");
  299.   ncolors=number_colors;
  300.   bg=0;
  301.   pal=(color *)jmalloc(ncolors*3,"palette");
  302.   usd=(unsigned char *)jmalloc(ncolors/8+1,"palette used array");
  303.   defaults();
  304. }
  305.  
  306.  
  307.  
  308. quant_node::~quant_node()
  309. {
  310. /*  if (!is_leaf())
  311.   { for (i=0;i<8;i++)
  312.       if (children[i])
  313.       {    delete children[i];
  314.     children[i]=NULL;
  315.       }
  316.   } */
  317. }
  318.  
  319.  
  320. /*void quant_node::prune()
  321. {
  322.   int t,r,g,b;
  323.   CONDITION(!is_leaf(),"Cannot prune a leaf!");
  324.   total(t,r,g,b);
  325.   red=r/t;
  326.   green=g/t;
  327.   blue=b/t;
  328.   be_childish();
  329. } */
  330.  
  331. void quant_node::total(int &tnodes, int &tr, int &tg, int &tb)
  332. {
  333.   int i;
  334.   if (is_leaf())
  335.   { tnodes+=tot;
  336.     tr+=red*tot;
  337.     tg+=green*tot;
  338.     tb+=blue*tot;
  339.   }
  340.   else
  341.   { for (i=0;i<8;i++)
  342.       if (children[i])
  343.     children[i]->total(tnodes,tr,tg,tb);
  344.   }
  345. }
  346.  
  347. quant_node::quant_node(int level, quant_node *dad,
  348.     unsigned char r, unsigned char g, unsigned char b)
  349. {
  350.   int i;
  351.   CONDITION(level<=8,"Tree cannot have more than eight levels");
  352.   if (level==8)
  353.     be_childish();
  354.   else
  355.     for (i=0;i<8;i++) children[i]=NULL;
  356.   padre=dad;
  357.   red=r; green=g; blue=b;
  358.   tot=0;
  359. }
  360.  
  361. quant_palette::quant_palette(int max_colors)
  362. { root=NULL; nc=0; mx=max_colors; }
  363.  
  364. void quant_palette::re_delete(quant_node *who, int lev)  // removes all children from memory
  365. { int x;                                  // and recurses down
  366.   if (who)
  367.   {
  368.     if (!who->is_leaf())
  369.     { for (x=0;x<8;x++)
  370.     if (who->children[x])
  371.     {
  372.       CONDITION(lev<8,"Levl > 7");
  373.       re_delete(who->children[x],lev+1);
  374.       level[lev].unlink((linked_node *)who->children[x]);
  375.       delete who->children[x];
  376.     }
  377.     }
  378.   }
  379. }
  380.  
  381. void quant_palette::prune()
  382. {
  383.   int pruned,lev,x,r,g,b,t;
  384.   quant_node *p,*f;
  385.   for (pruned=0,lev=8;lev>1 && !pruned;lev--)
  386.   {
  387.     p=(quant_node *)level[lev-1].first();
  388.     if (p)
  389.     { do
  390.       {
  391.     f=p->father();
  392.     for (x=0;x<8 && !pruned;x++)
  393.       if (f->children[x])
  394.         if (f->children[x]->next()!=p->next())        // if this son is not me!
  395.         pruned=1;                   //  I have a brother! stop
  396.        p=(quant_node *)p->next();
  397.       } while ((linked_node *) p!=level[lev-1].first() && !pruned);
  398.     }
  399.   }
  400.   CONDITION(lev>0,"could not prune!");
  401.   t=0; r=0; g=0; b=0;
  402.   f->total(t,r,g,b);
  403.   if (t<=1)
  404.   {
  405.     t=0; r=0; g=0; b=0;
  406.     f->total(t,r,g,b);
  407.   }
  408.   CONDITION(t>1,"Should be more colors\n");
  409.   printf("%d Pruned at level %d, r=%d, g=%d, b=%d, total nodes off = %d\n",nc,
  410.     lev,r/t,g/t,b/t,t);
  411.   f->set(r/t,g/t,b/t);
  412.   nc-=t;
  413.   nc++;
  414.   re_delete(f,lev);
  415.   f->be_childish();
  416. }
  417.  
  418. void quant_palette::add_color(unsigned char r, unsigned char g, unsigned char b)
  419. {
  420.   quant_node **p,*fat;
  421.   int lev,cn,stop;
  422.   p=&root;
  423.   lev=0;
  424.   stop=0;
  425.   fat=NULL;
  426.   if (nc>=mx-1)
  427.     prune();
  428.   while (!stop)
  429.   {
  430.     lev++;
  431.     if (!(*p))
  432.     { 
  433.       if (lev>2 && !fat)
  434.     printf("h");
  435.       (*p)=new quant_node(lev,fat);
  436.       level[lev-1].add_end((linked_node *)(*p));
  437.     }
  438.  
  439.     if (!(*p)->is_leaf())
  440.     {
  441.       cn=((r&(256>>lev))!=0)<<2;
  442.       cn+=((g&(256>>lev))!=0)<<1;
  443.       cn+=((b&(256>>lev))!=0);
  444.       fat=(*p);
  445.       p=&((*p)->children[cn]);
  446.     } else stop=1;
  447.  
  448.   }
  449.   (*p)->set(r,g,b);
  450.   if (!(*p)->tot)
  451.     nc++;
  452.   (*p)->tot++;
  453. }
  454.  
  455. palette *quant_palette::create_pal()
  456. {
  457.   palette *p;
  458.   int i,x;
  459.   quant_node *pn;
  460.   p=new palette(mx);
  461.   for (x=0,i=7;i>=0;i++)
  462.     for (pn=(quant_node *)level[i].first();
  463.      pn!=(quant_node *)level[i].first();pn=(quant_node *)pn->next())
  464.       if (pn->is_leaf())
  465.     p->set(x++,pn->red,pn->green,pn->blue);
  466.   return p;
  467. }
  468.  
  469. quant_palette::~quant_palette()
  470. {
  471.   if (root)
  472.   {
  473.     re_delete(root,1);
  474.     delete root;
  475.   }
  476. }
  477.  
  478. unsigned char palette::brightest(int all)
  479. { unsigned char r,g,b,bri;
  480.   unsigned i;
  481.   long brv;
  482.   brv=0; bri=0;
  483.  
  484.   for (i=0;i<ncolors;i++)
  485.   { if (all || used(i))
  486.     {
  487.       get(i,r,g,b);
  488.       if ((long)r*(long)g*(long)b>brv)
  489.       { brv=(long)r*(long)g*(long)b;
  490.     bri=i;
  491.       }
  492.     }
  493.   }
  494.  
  495.   return bri;
  496. }
  497.  
  498. unsigned char palette::darkest(int all, int noblack)
  499. { unsigned char r,g,b,bri;
  500.   unsigned i;
  501.   long brv,x;
  502.   brv=(long)258*(long)258*(long)258; bri=0;
  503.  
  504.   for (i=0;i<ncolors;i++)
  505.   { if (all || used(i))
  506.     {
  507.       get(i,r,g,b);
  508.       x=(long)r*(long)g*(long)b;
  509.       if (x<brv && (x || !noblack))
  510.       { brv=(long)r*(long)g*(long)b;
  511.     bri=i;
  512.       }
  513.     }
  514.   }
  515.   return bri;
  516. }
  517.  
  518.  
  519.  
  520. palette *last_loaded()
  521. { return lastl; }
  522.  
  523. void palette::fade_to(int total_fades, int fade_on, int dest_r, int dest_g, int dest_b)
  524. {
  525.   unsigned char *sl=(unsigned char *)addr();
  526.   int i;  
  527.   for (i=0;i<ncolors;i++)
  528.   {
  529.     *(sl++)=(( dest_r-(int)*sl)*fade_on/total_fades+*sl);
  530.     *(sl++)=(( dest_g-(int)*sl)*fade_on/total_fades+*sl);
  531.     *(sl++)=(( dest_b-(int)*sl)*fade_on/total_fades+*sl);    
  532.   }  
  533. }
  534.